package gui;

import gui.actions.CleanupAction;
import gui.actions.QuitAction;
import gui.actions.ResetAction;
import gui.frames.ConfigurationsFrame;
import gui.frames.MainMenuFrame;
import gui.frames.PlayFrame;
import gui.frames.SetupFrame;
import gui.frames.StatisticsFrame;
import gui.panels.InfiniteProgressPanel;
import gui.utils.Settings;

import java.awt.Dimension;
import java.util.Properties;

import javax.swing.AbstractAction;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JRadioButton;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.plaf.metal.DefaultMetalTheme;
import javax.swing.plaf.metal.MetalLookAndFeel;

import com.jgoodies.clearlook.ClearLookManager;
import com.jgoodies.plaf.Options;
import com.jgoodies.plaf.plastic.PlasticLookAndFeel;

import common.Fictionator;
import common.models.StatisticsModel;

public class GuiManager {

	private static JFrame prevFrame = null;
	private static JFrame currFrame = null;
	private static boolean isNimbusLookAndFeelInstalled = false;
	private static InfiniteProgressPanel glassPane = new InfiniteProgressPanel();
	
	public static JFrame getCurrentFrame() {
		return currFrame;
	}
	
	public static InfiniteProgressPanel getGlassPane() {
		return glassPane;
	}
	
	public static void quitApplication() {
	    QuitAction quitAction = new QuitAction();
	    quitAction.quit();
	}
	
	public static void disposeAndExit() {
        if (prevFrame != null) {
            prevFrame.dispose();
        }
        currFrame.dispose();
        System.exit(0);
	}
	
	public static void switchFrame(FramesEnum framesEnum) {
		switchFrame(framesEnum,null);
	}
	
	public static void switchFrame(FramesEnum framesEnum, Object model) {
	    
	    installLookAndFeel(framesEnum);
	    
		if (currFrame == null) {
			currFrame = new MainMenuFrame();
		} else if (framesEnum.equals(FramesEnum.PREVIOUS_FRAME)) {
			currFrame.dispose();
			currFrame = prevFrame;	
			prevFrame = null;
			if (currFrame == null) {
				currFrame = new MainMenuFrame();
			}
		} else {
			if (prevFrame != null) {
				prevFrame.dispose();
			}
			prevFrame = currFrame;
			prevFrame.setVisible(false);
			
			switch (framesEnum) {
				case MAIN_MENU_FRAME:
					currFrame = new MainMenuFrame();
					break;
				case PLAY_FRAME:
					currFrame = new PlayFrame();
					break;
				case STATISTICS_FRAME:
					currFrame = new StatisticsFrame((StatisticsModel) model);
					break;
				case CONFIGURATION_FRAME:
					currFrame = new ConfigurationsFrame();
					break;	
			}	
		}	
				
		currFrame.setVisible(true);	
		currFrame.setGlassPane(getGlassPane());
	}
	
	public static enum FramesEnum {
		MAIN_MENU_FRAME(true),
		PLAY_FRAME(true),
		CONFIGURATION_FRAME(false),
		STATISTICS_FRAME(true),
		PREVIOUS_FRAME(true);
		
		private final boolean isNimbusLookAndFeel;

		FramesEnum(boolean isNimbusLookAndFeel) {
			this.isNimbusLookAndFeel = isNimbusLookAndFeel;	
		}
	}
	
	private static void installLookAndFeel() {
		installLookAndFeel(FramesEnum.MAIN_MENU_FRAME);
	}
	
	private static void installLookAndFeel(FramesEnum framesEnum) {
		try {
			if (framesEnum.isNimbusLookAndFeel && !isNimbusLookAndFeelInstalled) {	
			    for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
			        if ("Nimbus".equals(info.getName())) {			        
			            UIManager.setLookAndFeel(info.getClassName());			            
			            isNimbusLookAndFeelInstalled = true;
			            break;
			        }
			    }    
			} else if (!framesEnum.isNimbusLookAndFeel && isNimbusLookAndFeelInstalled) {
				UIManager.getLookAndFeelDefaults();
		    	Settings settings = Settings.createDefault();
		        Options.setDefaultIconSize(new Dimension(18, 18));

		        UIManager.put(Options.USE_SYSTEM_FONTS_APP_KEY, settings.isUseSystemFonts());
		        Options.setGlobalFontSizeHints(settings.getFontSizeHints());
		        Options.setUseNarrowButtons(settings.isUseNarrowButtons());

		        Options.setTabIconsEnabled(settings.isTabIconsEnabled());
		        ClearLookManager.setMode(settings.getClearLookMode());
		        ClearLookManager.setPolicy(settings.getClearLookPolicyName());
		        UIManager.put(Options.POPUP_DROP_SHADOW_ENABLED_KEY, settings.isPopupDropShadowEnabled());

		        LookAndFeel selectedLaf = settings.getSelectedLookAndFeel();
		        if (selectedLaf instanceof PlasticLookAndFeel) {
		            PlasticLookAndFeel.setMyCurrentTheme(settings.getSelectedTheme());
		            PlasticLookAndFeel.setTabStyle(settings.getPlasticTabStyle());
		            PlasticLookAndFeel.setHighContrastFocusColorsEnabled(
		                settings.isPlasticHighContrastFocusEnabled());
		        } else if (selectedLaf.getClass() == MetalLookAndFeel.class) {
		            MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme());
		        }

		        JRadioButton radio = new JRadioButton();
		        radio.getUI().uninstallUI(radio);
		        JCheckBox checkBox = new JCheckBox();
		        checkBox.getUI().uninstallUI(checkBox);	
		        
		        UIManager.setLookAndFeel(selectedLaf);
		        isNimbusLookAndFeelInstalled = false;
			}
		} catch (Exception e) {
			System.err.println("Can't change L&F: " + e);
		}
	}
	
	public static void startGui() {
		switchFrame(FramesEnum.MAIN_MENU_FRAME);
		CleanupAction cleanupAction = new CleanupAction();
		cleanupAction.actionPerformed(null);
	}
	
	public static void showSetupFrame(Properties properties, AbstractAction applyAction) {
		installLookAndFeel();
		SetupFrame setupFrame = new SetupFrame(properties, applyAction);
		setupFrame.setVisible(true);
	}

    public static void showStartupProblemDialog() {
    	installLookAndFeel();
        String message = "There was a problem starting fictionator.\n" +
        		"Is your connection properly configured?\n" +
        		"Run setup in order to configure connection.";
        String title = "Startup Problem";
        JOptionPane.showMessageDialog(null, message, title, JOptionPane.ERROR_MESSAGE);
        try {
            Fictionator.getInstance().getConfigurationsLogic().closeResources();
        } catch (Exception e) { /* do nothing */ }

    }

    public static void showPossibleOngoinImportDialog() {
    	installLookAndFeel();
        String message = "There seems to be an ongoing import right now.\nYou may however, forcibly clean all other user sessions";
        message += " by clicking 'Force Clean'.\n Either way you will have to restart Fictionator";
        String title = "Possible ongoing import";
        String[] options = { "Force clean", "Get me out of here" };
        
        int choice = JOptionPane.showOptionDialog(null, message, title, 0, JOptionPane.INFORMATION_MESSAGE, null, options, null);

        if (choice == 0) {
            ResetAction reset = new ResetAction();
            reset.run();
        } else {
            try {
                Fictionator.getInstance().getConfigurationsLogic().closeResources();
            } catch (Exception e) { /* do nothing */ }
        }
    }
    
    public static boolean showInstallProceedDialog() {
    	installLookAndFeel();
        String message = "This install program will initialize the database and fill it with the needed data for the game.\n";
        message += "In order to download the data you must have an open internet connection.\n";
        message += "Also all previous data in the database will be lost.\n";
        message += "Would you like to proceed?\n";
        String title = "Install";
        String[] options = { "Install", "Cancel" };
        
        int choice = JOptionPane.showOptionDialog(null, message, title, 0, JOptionPane.WARNING_MESSAGE, null, options, null);
        return choice == 0;
    }
    
}
